package com.cskaoyan.javase.oop3._1interface._0introduction;

/**
 * 现在我们有了新需求：一部分猫和狗，经过了特殊训练，能够直立行走了。
 * 那么这群特殊的猫和狗，怎么描述它们呢？
 *
 * 分析：
 * 部分猫和狗经过特殊训练，才能够直立行走。
 * 所以不可能直接加个方法到Cat类和Dog类中，不是所有猫狗都有这个行为。
 * 而特殊的猫狗仍然是猫和狗，所以它们肯定还要继承猫和狗这两个类。
 * 可能很多同学，这时候想到的就是：重新定义两个新的猫狗类（比如超级狗和猫）继承猫狗，然后给出直立行走的方法就算完事了。这样做不是不行，需求是实现了，但还有一些小问题：
 * 一方面没有体现代码复用。
 * 更重要的是，没有体现出特殊训练的过程。
 *
 * 假如还有一些动物也要直立行走，增加这个行为，如何体现出规范性、标准性呢？体现出它们是特殊的经过训练的动物呢？
 * 这里我们想到了抽象类，因为抽象类中抽象方法，可以强制约束子类实现它，这样就是一种标准和规范，体现了它经过了特殊训练，和之前不同了。
 *
 * 于是我们定义抽象类，给出抽象方法，让超级猫狗类去继承这个抽象类，可行吗？
 *
 * 理想很美好，现实很骨感。显然做不到，因为Java不支持多继承。除开这点这么做也不是完美的，问题是：
 *
 *      1.语法上限制了,Java不支持多继承
 *      2.这个抽象类里面是对功能和行为的抽象，缺少属性（单独一个直立行走的行为是一个什么对象？）所以单独的行为不应该被抽象为类，不符合类的定义。
 *      3.继承这个抽象类也不符合继承的"is-a"关系，这里不适用继承（还是上面那句话，行为根本不是个体）
 *      4.抽象类是作为继承层次中的祖先类存在的
 *          这个抽象的技能类和祖先类没有任何关系.
 *
 * 于是，我们就迫切需要一种全新的数据类型，这种全新的数据类型：
 *
 *      1.不强调属性，只强调行为的抽象，"继承"它表示功能的扩展。
 *      2.在一个类继承某个类后，还能继续"继承"，不受Java单继承限制。
 *      3.没有"is-a"这种继承关系的限制。
 *      4.最好还有抽象方法。（因为它能表示规范和标准）
 *
 * 这种全新的数据类型，就是接口（interface）。
 *
 * 上面四条，其实已经描述了接口的特点
 * 接口是一种表示对行为抽象的，不受Java多继承限制的，用来作为功能扩展标准的一种新的引用数据类型。
 * 它的定义语法如下：
 * [访问权限修饰符] interface 接口名{
 *     // 接口体
 * }
 *
 * 解释:
 *      1.访问权限修饰符,接口和类的是一样的
 *      2.接口和类是同等级别的数据类型,都是引用数据类型,它们是平行的关系
 *      3.接口的声明使用关键字interface
 *      4.接口名和类名一样,大驼峰式书写
 *      5.接口体的书写和类体类似,接口中可以定义抽象方法.
 *
 * 接口的"继承":
 *      类"继承"接口,更准确的说法是类"实现"接口
 *      使用关键字"implements"
 *      普通类实现接口,必须要实现接口中的抽象方法
 *      接口中的抽象方法和抽象类中的抽象方法,效果完全一样.
 *      接口的实现,不受Java单继承限制
 *      一个类可以在继承类的同时再实现接口
 *      (要先extends继承类,再implements实现接口)
 *      Java类实现接口,是"多实现"的
 *      一个类可以实现很多个接口
 *
 *      某个类实现接口,那么该类和接口之间是"父接口"和"实现类"的关系
 *          实际上就是父类和子类的关系.
 *
 *      接口的实现和继承实际上就是一回事
 *          类实现接口会得到接口中的成员(如果是抽象方法,就需要普通实现类实现)
 *
 *
 * 使用接口有如下优点：
 *      1.接口不受单继承限制，这是接口非常重要的优点。
 *      2.接口不是类，它和它的实现类，也不需要存在"is-a"关系，接口比抽象类的使用更加灵活。
 *          程序开发中将接口和它的实现类之间的关系，称之为"like-a"关系。
 *          只要是实现了Xxx的功能，就像Xxx。
 *      3.接口表示一种开发标准，一种规范。
 *          表示对功能的扩展，它只关注行为，不关注属性。
 *
 *
 * @since 09:31
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 父类引用会限制子类对象的访问范围
        Animal ani = new SpecialCat();
        ani.shout();
        ((SpecialCat) ani).walkUpright();

        Cat c = new SpecialCat();
        c.catOnly();

        SpecialSkill ss = new SpecialCat();
        ss.walkUpright();

        A a = new SpecialCat();
        ((SpecialCat) a).walkUpright();
    }
}

abstract class Animal {
    public abstract void shout();
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }

    public void catOnly(){}
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}

// 技能抽象类
abstract class AbstractSkill {
    public abstract void walkUpright();
}

class SpecialCat extends Cat implements SpecialSkill,A{
    @Override
    public void walkUpright() {
        System.out.println("我是超威蓝猫,我可以直立行走");
    }
}

class SpecialDog extends Dog implements SpecialSkill {
    @Override
   public void walkUpright() {
        System.out.println("我是汪汪队,我可以直立行走");
    }
}

interface SpecialSkill {
    public abstract void walkUpright();
}

interface A{

}